<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - physically based shading</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                color: #fff;
                font-family: Monospace;
                font-size: 13px;
                text-align: center;
                font-weight: bold;

                background-color: #000;
                margin: 0px;
                overflow: hidden;
            }

            #info {
                position: absolute;
                width: 100%;
                text-align: center;
                padding: 5px;
            }

            a { color: skyblue; }
        </style>
        <script>
 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-89125623-1', 'auto');
  ga('send', 'pageview');
    </script>
    </head>

    <body>
        <div id="info">
            <a href="http://threejs.org" target="_blank">three.js</a> - webgl physically based shading testbed
        </div>

<div class="buttonHolder" style="position:relative;text-align:center;top:40px">
<button class="startButton" onclick="startCapture360()">Start Capture</button>
<button class="saveButton"  onclick="stopCapture360()">Stop Capture</button>
</div>

        <script src="js/three.min.js"></script>

        <script src="js/TrackballControls.js"></script>

<!-- movie capture section -->
<script src="js/CCapture.js"></script>
<!-- Include tar.js if you want to export PNG or JPEG -->
<script src="js/tar.js"></script>
<!-- Include download.js for easier file download -->
<script src="js/download.js"></script>
<!-- 360 capture section -->
<script src="js/CubemapToEquirectangular.js"></script>

<script>

            var container;

            var camera, scene, renderer, canvas;

            var mesh, geometry;

            var cubeCamera;

            var sunLight, pointLight, ambientLight;

            var mixer;

            var clock = new THREE.Clock();

            var shadowCameraHelper, shadowConfig = {

                shadowCameraVisible: false,
                shadowCameraNear: 750,
                shadowCameraFar: 4000,
                shadowCameraFov: 30,
                shadowBias: -0.0002

            };


// Create a capturer that exports Equirectangular 360 JPG images in a TAR file
var capturer360 = new CCapture({
    format: 'threesixty',
    display:true,
    autoSaveTime: 3,
});


function startCapture360(event) {
    capturer360.start();
}

function saveCapture360(event) {

    capturer360.save();
}

function stopCapture360(event) {
    capturer360.stop();
}


function capture360(event) {
    return equiManaged.update(camera, scene);
}





            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                // CAMERA

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 2, 10000 );
                camera.position.set( 500, 400, 1200 );

                // SCENE

                scene = new THREE.Scene();
                scene.fog = new THREE.Fog( 0, 1000, 10000 );

                // CUBE CAMERA

                cubeCamera = new THREE.CubeCamera( 1, 10000, 128 );

                // TEXTURES
                var textureLoader = new THREE.TextureLoader();

                var textureSquares = textureLoader.load( "textures/bright_squares256.png" );
                textureSquares.repeat.set( 50, 50 );
                textureSquares.wrapS = textureSquares.wrapT = THREE.RepeatWrapping;
                textureSquares.magFilter = THREE.NearestFilter;
                textureSquares.format = THREE.RGBFormat;

                var textureNoiseColor = textureLoader.load( "textures/disturb.jpg" );
                textureNoiseColor.repeat.set( 1, 1 );
                textureNoiseColor.wrapS = textureNoiseColor.wrapT = THREE.RepeatWrapping;
                textureNoiseColor.format = THREE.RGBFormat;

                var textureLava = textureLoader.load( "textures/lavatile.jpg" );
                textureLava.repeat.set( 6, 2 );
                textureLava.wrapS = textureLava.wrapT = THREE.RepeatWrapping;
                textureLava.format = THREE.RGBFormat;

                //

                var path = "textures/SwedishRoyalCastle/";
                var format = '.jpg';
                var urls = [
                        path + 'px' + format, path + 'nx' + format,
                        path + 'py' + format, path + 'ny' + format,
                        path + 'pz' + format, path + 'nz' + format
                    ];

                var reflectionCube = new THREE.CubeTextureLoader().load( urls );

                // GROUND

                var groundMaterial = new THREE.MeshPhongMaterial( {
                    shininess: 80,
                    color: 0xffffff,
                    specular: 0xffffff,
                    map: textureSquares
                } );

                var planeGeometry = new THREE.PlaneBufferGeometry( 100, 100 );

                var ground = new THREE.Mesh( planeGeometry, groundMaterial );
                ground.position.set( 0, 0, 0 );
                ground.rotation.x = - Math.PI / 2;
                ground.scale.set( 1000, 1000, 1000 );
                ground.receiveShadow = true;
                scene.add( ground );

                // MATERIALS

                var materialLambert = new THREE.MeshPhongMaterial( { shininess: 50, color: 0xffffff, map: textureNoiseColor } );
                var materialPhong = new THREE.MeshPhongMaterial( { shininess: 50, color: 0xffffff, specular: 0x999999, map: textureLava } );
                var materialPhongCube = new THREE.MeshPhongMaterial( { shininess: 50, color: 0xffffff, specular: 0x999999, envMap: cubeCamera.renderTarget.texture } );

                // OBJECTS

                var sphereGeometry = new THREE.SphereGeometry( 100, 64, 32 );
                var torusGeometry = new THREE.TorusGeometry( 240, 60, 32, 64 );
                var cubeGeometry = new THREE.BoxGeometry( 150, 150, 150 );

                addObject( torusGeometry, materialPhong, 0, 100, 0, 0 );
                addObject( cubeGeometry, materialLambert, 350, 75, 300, 0 );

                mesh = addObject( sphereGeometry, materialPhongCube, 350, 100, -350, 0 );
                mesh.add( cubeCamera );

                function addObjectColor( geometry, color, x, y, z, ry ) {

                    var material = new THREE.MeshPhongMaterial( { color: 0xffffff } );

                    return addObject( geometry, material, x, y, z, ry );

                }

                function addObject( geometry, material, x, y, z, ry ) {

                    var tmpMesh = new THREE.Mesh( geometry, material );

                    tmpMesh.material.color.offsetHSL( 0.1, -0.1, 0 );

                    tmpMesh.position.set( x, y, z );

                    tmpMesh.rotation.y = ry;

                    tmpMesh.castShadow = true;
                    tmpMesh.receiveShadow = true;

                    scene.add( tmpMesh );

                    return tmpMesh;

                }

                var bigCube = new THREE.BoxGeometry( 50, 500, 50 );
                var midCube = new THREE.BoxGeometry( 50, 200, 50 );
                var smallCube = new THREE.BoxGeometry( 100, 100, 100 );

                addObjectColor( bigCube,   0xff0000, -500, 250, 0, 0 );
                addObjectColor( smallCube, 0xff0000, -500, 50, -150, 0 );

                addObjectColor( midCube,   0x00ff00, 500, 100, 0, 0 );
                addObjectColor( smallCube, 0x00ff00, 500, 50, -150, 0 );

                addObjectColor( midCube,   0x0000ff, 0, 100, -500, 0 );
                addObjectColor( smallCube, 0x0000ff, -150, 50, -500, 0 );

                addObjectColor( midCube,   0xff00ff, 0, 100, 500, 0 );
                addObjectColor( smallCube, 0xff00ff, -150, 50, 500, 0 );

                addObjectColor( new THREE.BoxGeometry( 500, 10, 10 ), 0xffff00, 0, 600, 0, Math.PI/4 );
                addObjectColor( new THREE.BoxGeometry( 250, 10, 10 ), 0xffff00, 0, 600, 0, 0 );

                addObjectColor( new THREE.SphereGeometry( 100, 32, 26 ), 0xffffff, -300, 100, 300, 0 );

                // MORPHS

                var loader = new THREE.JSONLoader();

                loader.load( "textures/sittingBox.js", function( geometry ) {

                    var morphMaterial = new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0xff9900, shininess: 50, morphTargets: true, side: THREE.DoubleSide, shading: THREE.FlatShading } );

                    var mesh = new THREE.Mesh( geometry, morphMaterial );

                    mixer = new THREE.AnimationMixer( mesh );

                    mixer.clipAction( geometry.animations[0] ).setDuration( 10 ).play();

                    var s = 200;
                    mesh.scale.set( s, s, s );

                    mesh.castShadow = true;
                    mesh.receiveShadow = true;

                    scene.add( mesh );

                } );

                // LIGHTS

                ambientLight = new THREE.AmbientLight( 0x3f2806 );
                scene.add( ambientLight );

                pointLight = new THREE.PointLight( 0xffaa00, 1, 5000 );
                scene.add( pointLight );

                sunLight = new THREE.SpotLight( 0xffffff, 0.3, 0, Math.PI/2 );
                sunLight.position.set( 1000, 2000, 1000 );

                sunLight.castShadow = true;

                sunLight.shadow = new THREE.LightShadow( new THREE.PerspectiveCamera( shadowConfig.shadowCameraFov, 1, shadowConfig.shadowCameraNear, shadowConfig.shadowCameraFar ) );
                sunLight.shadow.bias = shadowConfig.shadowBias;

                scene.add( sunLight );

                // SHADOW CAMERA HELPER

                shadowCameraHelper = new THREE.CameraHelper( sunLight.shadow.camera );
                shadowCameraHelper.visible = shadowConfig.shadowCameraVisible;
                scene.add( shadowCameraHelper );

                // RENDERER

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                canvas=container.appendChild( renderer.domElement );

                //

                renderer.shadowMap.enabled = true;
                renderer.shadowMap.type = THREE.PCFSoftShadowMap;

                //

                renderer.gammaInput = true;
                renderer.gammaOutput = true;

                //
                 equiManaged = new CubemapToEquirectangular(renderer, true,"4K");

                controls = new THREE.TrackballControls( camera, renderer.domElement );
                controls.target.set( 0, 120, 0 );

                controls.rotateSpeed = 1.0;
                controls.zoomSpeed = 1.2;
                controls.panSpeed = 0.8;

                controls.noZoom = false;
                controls.noPan = false;

                controls.staticMoving = true;
                controls.dynamicDampingFactor = 0.15;

                controls.keys = [ 65, 83, 68 ];



            }

            //

            function onWindowResize( event ) {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

                controls.handleResize();

            }

            //

            function animate() {

                requestAnimationFrame( animate );

                render();

            }

            function render() {

                // update

                var delta = clock.getDelta();

                controls.update();

                if ( mixer ) {

                    mixer.update( delta );

                }

                // render cube map

                mesh.visible = false;
                cubeCamera.updateCubeMap( renderer, scene );
                mesh.visible = true;

                // render scene

                renderer.render( scene, camera );
                capturer360.capture(canvas);
            
            }

        </script>


    </body>
</html>
